import sys
import json
from PyQt5.QtWidgets import (
    QWidget,
    QHBoxLayout,
    QPushButton,
    QMessageBox,
    QVBoxLayout,
    QComboBox,
)
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
from abc import ABC, abstractmethod, ABCMeta
from pydantic import ValidationError
from enum import Enum
import gui.controls.envs as envs
from .c_list import CList
from .utils import Utils
from . import message_box as MBox


# 创建一个新的元类来解决冲突
class MetaClass(type(QWidget), ABCMeta):
    pass


class InstallComponent(QWidget, ABC, metaclass=MetaClass):

    def __init__(self, parent=None):
        super(InstallComponent, self).__init__(parent)

        self.hLayout = QHBoxLayout()

        self.model = self.get_model()
        if self.model is None:
            raise ValueError("子类必须通过 get_model() 方法设置 model")

        self.pBtnAdd = QPushButton("添加")
        self.pBtnAdd.setObjectName("pBtnAdd")
        self.pBtnAdd.clicked.connect(self.on_pBtnAdd_clicked)
        self.pBtnEdit = QPushButton("编辑")
        self.pBtnEdit.setObjectName("pBtnEdit")
        self.pBtnEdit.clicked.connect(self.on_pBtnEdit_clicked)
        self.pBtnDel = QPushButton("删除")
        self.pBtnDel.setObjectName("pBtnDel")
        self.pBtnDel.clicked.connect(self.on_pBtnDel_clicked)
        self.pBtnDraw = QPushButton("绘制线段")
        self.pBtnDraw.setObjectName("pBtnDraw")
        self.pBtnDraw.clicked.connect(self.on_pBtnDraw_clicked)
        self.pBtnOther1 = QPushButton("")
        self.pBtnOther1.setVisible(False)
        self.pBtnOther1.setObjectName("pBtnOther1")
        self.pBtnOther1.clicked.connect(self.on_pBtnOther1_clicked)
        self.pBtnOther2 = QPushButton("")
        self.pBtnOther2.setVisible(False)
        self.pBtnOther2.setObjectName("pBtnOther2")
        self.pBtnOther2.clicked.connect(self.on_pBtnOther2_clicked)
        self.pBtnAdd.setFixedHeight(30)
        self.pBtnAdd.setMinimumWidth(80)
        self.pBtnEdit.setFixedHeight(30)
        self.pBtnEdit.setMinimumWidth(80)
        self.pBtnDel.setFixedHeight(30)
        self.pBtnDel.setMinimumWidth(80)
        self.pBtnDraw.setFixedHeight(30)
        self.pBtnDraw.setMinimumWidth(116)
        self.pBtnOther1.setFixedHeight(30)
        self.pBtnOther1.setMinimumWidth(80)
        self.pBtnOther2.setFixedHeight(30)
        self.pBtnOther2.setMinimumWidth(80)

        self.pBtnDraw.setVisible(False)

        # self.hLayout.addStretch(1)
        self.hLayout.setAlignment(Qt.AlignCenter)  # 设置居中对齐
        self.hLayout.addWidget(self.pBtnAdd)
        self.hLayout.addWidget(self.pBtnEdit)
        self.hLayout.addWidget(self.pBtnDel)
        self.hLayout.addWidget(self.pBtnDraw)
        self.hLayout.addWidget(self.pBtnOther1)
        self.hLayout.addWidget(self.pBtnOther2)
        # self.hLayout.addStretch(1)

        self.vLayout = QVBoxLayout()
        self.vLayout.addLayout(self.hLayout)

        self.layout = QHBoxLayout()
        self.listWidget = CList()
        self.listWidget.itemClicked.connect(self.onItemClicked)
        self.layout.addLayout(self.vLayout)
        self.layout.addWidget(self.listWidget)

        self.setLayout(self.layout)

    @abstractmethod
    def get_model(self):
        """
        抽象方法：子类必须实现此方法来设置数据模型
        Returns:
            返回一个 Pydantic model 类
        """
        pass

    @abstractmethod
    def get_widgetDict(self):
        """
        抽象方法：子类必须实现此方法来返回widget字典
        Returns:
            返回一个 包含widget 字典
        """
        pass

    def updateUi(self, data):
        self.listWidget.updateUi(data)

    def updateUiTable(self, data):
        self.listWidget.updateUi(data)

    def on_pBtnAdd_clicked(self):
        return self.validateParams()

    def on_pBtnEdit_clicked(self):
        return self.validateParams()

    def on_pBtnDraw_clicked(self):
        pass

    def on_pBtnOther1_clicked(self):
        pass

    def on_pBtnOther2_clicked(self):
        pass

    def on_pBtnDel_clicked(self):
        isDel = MBox.confirm("是否确认删除?")
        if isDel:
            self.listWidget.takeItem(self.listWidget.currentRow())
            self.clearValue()

    def validateParams(self, patch=None):
        try:
            field_values = {}
            for field_name, widget in self.get_widgetDict().items():
                field_info = self.model.model_fields[field_name]
                if isinstance(widget, QComboBox):
                    enum_type = field_info.annotation
                    selected_text = widget.currentText()
                    if isinstance(enum_type, type) and issubclass(enum_type, Enum):
                        enum_value = next(
                            (
                                item.value
                                for item in enum_type
                                if item.alias == selected_text
                            ),
                            None,
                        )
                        if not enum_value and field_info.is_required():
                            raise ValueError(f"'{field_info.description}' 不能为空")
                        field_values[field_info.alias] = enum_value  # 使用 alias
                    else:
                        field_values[field_info.alias] = selected_text  # 使用 alias
                else:
                    text_value = widget.text().strip()
                    if not text_value and field_info.is_required():
                        raise ValueError(f"'{field_info.description}' 不能为空")
                    field_values[field_info.alias] = text_value  # 使用 alias

            # 使用 pydantic 进行验证
            validated_data = self.model(**field_values)
            return validated_data.model_dump()

        except ValidationError as e:
            for error in e.errors():
                field = error["loc"][0]
                # 通过 alias 反查找字段名
                field_name = next(
                    (
                        name
                        for name, info in self.model.model_fields.items()
                        if info.alias == field
                    ),
                    field,
                )
                field_description = self.model.model_fields[field_name].description
                # 获取自定义错误信息或使用默认翻译
                error_msg = str(error["msg"]).replace("Value error,", "")
                # QMessageBox.warning(self, "警告", f"{field_description}: {error_msg}")
                MBox.warning(f"{field_description}: {error_msg}")
                return False
        except ValueError as e:
            # QMessageBox.warning(self, "警告", str(e))
            MBox.warning(str(e))
            return False

    def getValues(self):
        field_values = {}
        for field_name, widget in self.get_widgetDict().items():
            field_info = self.model.model_fields[field_name]
            field_type = field_info.annotation
            if isinstance(widget, QComboBox):
                selected_text = widget.currentText()
                if isinstance(field_type, type) and issubclass(field_type, Enum):
                    enum_value = next(
                        (
                            item.value
                            for item in field_type
                            if item.alias == selected_text
                        ),
                        None,
                    )
                    field_values[field_info.alias] = enum_value  # 使用 alias
                else:
                    field_values[field_info.alias] = selected_text  # 使用 alias
            else:
                text_value = widget.text().strip()
                if isinstance(field_type, type) and issubclass(field_type, float):
                    if text_value:
                        text_value = float(text_value)
                elif isinstance(field_type, type) and issubclass(field_type, int):
                    if text_value:
                        text_value = int(text_value)
                field_values[field_info.alias] = text_value  # 使用 alias
        # 使用 pydantic 进行验证
        # validated_data = self.model(**field_values)
        # return validated_data.model_dump()
        return field_values

    def clearValue(self):
        for _, widget in self.get_widgetDict().items():
            if isinstance(widget, QComboBox):
                widget.setCurrentIndex(0)
            else:
                widget.setText("")
